package com.example.kotlin.download

import android.os.AsyncTask
import android.os.Environment
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
import java.io.InputStream
import java.io.RandomAccessFile

/**
 * @ClassName: DownloadTask
 * @Description: java类作用描述
 * @Author: chenmengjia
 * @Date: 2022/2/23 10:01
 */
class DownloadTask(private val listener: DownloadListener?) : AsyncTask<String, Int, Int>() {
    companion object {
        const val TYPE_SUCCESS = 0
        const val TYPE_FAILED = 1
        const val TYPE_PAUSED = 2
        const val TYPE_CANCELLED = 3;
    }
    private var isCanceled = false
    private var isPaused = false
    private var lastProgress: Int = 0

    override fun doInBackground(vararg params: String): Int {

        var instr: InputStream? = null
        var savedFile: RandomAccessFile? = null
        var file: File? = null

        try {
            //已下载文件长度
            var downloadLength: Long = 0
            val downloadUrl = params[0]
            val fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"))
            val directory =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).path
            file = File(directory + fileName)
            if (file.exists()) {
                downloadLength = file.length()
            }
            val contentLength: Long = getContentLength(downloadUrl)
            if (contentLength == 0L) {
                return TYPE_FAILED
            } else if (contentLength == downloadLength) {
                return TYPE_SUCCESS
            }
            //断点下载

            val okHttpClient = OkHttpClient()
            val request =
                Request.Builder().addHeader("RANGE", "bytes=$downloadLength-").url(downloadUrl)
                    .build()
            val response = okHttpClient.newCall(request).execute()
            if (response != null) {
                instr = response.body()?.byteStream()
                savedFile = RandomAccessFile(file, "rw")
                savedFile.seek(downloadLength)//跳过已下载
                var total = 0
                var len: Int = 0
                val b = ByteArray(1024)
                while ((instr?.read(b).also { len = it ?:-1}) != -1) {
                    when {
                        isCanceled -> {
                            return TYPE_CANCELLED
                        }
                        isPaused -> {
                            return TYPE_PAUSED
                        }
                        else -> {
                            total += len
                            savedFile.write(b, 0, len)
                            val progress: Int =
                                (total + downloadLength * 100 / contentLength).toInt()
                            publishProgress(progress)
                        }
                    }
                }
                response.body()?.close()
                return TYPE_SUCCESS
            }
        } catch (e: Exception) {
            println(e.toString())
        } finally {

            try {
                instr?.close()
                savedFile?.close()
                if (isCanceled) {
                    file?.delete()
                }
            } catch (e: Exception) {

            }
        }
        return (TYPE_FAILED)

    }

    override fun onProgressUpdate(vararg values: Int?) {
        if (values != null) {
            val progress = values[0]
            progress?.let {
                if (it > lastProgress) {
                    listener?.onProgress(it)
                    lastProgress = progress
                }
            }
        }
    }

    override fun onPostExecute(result: Int?) {
        result?.let {

            when (result) {
                TYPE_SUCCESS -> {
                    listener?.onSuccess()
                }
                TYPE_FAILED -> {
                    listener?.onFailed()
                }
                TYPE_PAUSED -> {
                    listener?.onPause()
                }
                TYPE_CANCELLED -> {
                    listener?.onCancelled()
                }
                else -> {

                }
            }

        }

    }

    private fun getContentLength(downloadUrl: String): Long {
        val okHttpClient = OkHttpClient()
        val request = Request.Builder().url(downloadUrl).build()
        val response = okHttpClient.newCall(request).execute()
        if (response != null && response.isSuccessful) {
            val contentLength = response.body()?.contentLength()
            response.body()?.close()
            return contentLength?:0
        }

        return 0L
    }

    fun pauseDownload(){
        isPaused=true
    }

    fun cancelDownload(){
        isCanceled=true
    }
}